package com.czg.jsonschema2lombokpojo.annotator;

import com.czg.jsonschema2lombokpojo.AnnotationStyle;
import com.czg.jsonschema2lombokpojo.config.GenerationConfig;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 工厂对象，用于为所有支持的注解样式创建{@link Annotator}。
 */
public class AnnotatorFactory {

    private final GenerationConfig generationConfig;

    public AnnotatorFactory(GenerationConfig generationConfig) {
        this.generationConfig = generationConfig;
    }

    /**
     * 创建一个新的{@link Annotator}，可以根据给定的样式创建注解。
     *
     * @param style
     *            注解样式，指定需要什么样的注解。
     * @return 与给定样式匹配的注解器
     */
    public Annotator getAnnotator(AnnotationStyle style) {

        switch (style) {
            case JACKSON:
            case JACKSON2:
                return new Jackson2Annotator(generationConfig);
            case JSONB1:
                return new Jsonb1Annotator(generationConfig);
            case JSONB2:
                return new Jsonb2Annotator(generationConfig);
            case GSON:
                return new GsonAnnotator(generationConfig);
            case MOSHI1:
                return new Moshi1Annotator(generationConfig);
            case NONE:
                return new NoopAnnotator();
            default:
                throw new IllegalArgumentException("Unrecognised annotation style: " + style);
        }

    }

    /**
     * 从给定的类中创建一个新的自定义{@link Annotator}。
     *
     * @param clazz
     *            实现{@link Annotator}的类。
     * @return 给定注解器类型的实例
     */
    public Annotator getAnnotator(Class<? extends Annotator> clazz) {

        if (!Annotator.class.isAssignableFrom(clazz)) {
            throw new IllegalArgumentException("The class name given as a custom annotator (" + clazz.getName() + ") does not refer to a class that implements " + Annotator.class.getName());
        }

        try {
            try {
                Constructor<? extends Annotator> constructor = clazz.getConstructor(GenerationConfig.class);
                return constructor.newInstance(generationConfig);
            } catch (NoSuchMethodException e) {
                return clazz.newInstance();
            }
        } catch (InvocationTargetException | InstantiationException e) {
            throw new IllegalArgumentException("Failed to create a custom annotator from the given class. An exception was thrown on trying to create a new instance.", e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("Failed to create a custom annotator from the given class. It appears that we do not have access to this class - is both the class and its no-arg constructor marked public?", e);
        }

    }

    public CompositeAnnotator getAnnotator( Annotator... annotators ) {
        return new CompositeAnnotator(annotators);
    }

}
